﻿namespace FSharpChess
open System.Threading
open System
//Piece name options - only change on Promotion
//change this to a quicker enum
exception InvalidName
type enmName=
    |Pawn = 0
    |Bishop = 1
    |Knight = 2
    |Rook = 3
    |Queen = 4
    |King = 5
    |Null = 6
    
//Player setting
type oIntellegence=
    |Human
    |Computer
//fixed id for each of the 32 starting pieces
type enmID=
    |WhiteQueensRook = 0
    |WhiteQueensKnight = 1
    |WhiteQueensBishop = 2
    |WhiteQueen = 3
    |WhiteKing = 4
    |WhiteKingsBishop = 5
    |WhiteKingsKnight = 6
    |WhiteKingsRook = 7
    |WhitePawn1 = 8
    |WhitePawn2 = 9
    |WhitePawn3 = 10
    |WhitePawn4 = 11
    |WhitePawn5 = 12
    |WhitePawn6 = 13
    |WhitePawn7 = 14
    |WhitePawn8 = 15
    |BlackQueensRook = 16
    |BlackQueensKnight = 17
    |BlackQueensBishop = 18
    |BlackQueen = 19
    |BlackKing = 20
    |BlackKingsBishop = 21
    |BlackKingsKnight = 22
    |BlackKingsRook = 23
    |BlackPawn1 = 24
    |BlackPawn2 = 25
    |BlackPawn3 = 26
    |BlackPawn4 = 27
    |BlackPawn5 = 28
    |BlackPawn6 = 29
    |BlackPawn7 = 30
    |BlackPawn8 = 31
    |Null = 32
//types of moves
type oMoveName =
    |Standard
    |CastleQueenSide
    |CastleKingSide
    |PawnPromotionQueen
    |PawnPromotionRook
    |PawnPromotionKnight
    |PawnPromotionBishop
    |EnPassent
    |NullMove
//stages of the game
type oStage =
    |Opening
    |Middle
    |End
//Board Orientation
type oOrientation =
    |OriWhite
    |OriBlack
//Piece
type Piece =
    {
        Name: enmName;
        SquareOrd: int;
        pcIsWhite: bool;
        LastMoveTurnNo: int;
        NoOfMoves: int;
        HasBeenPromoted: bool;
        ID: enmID;
    }
    static member abbrev(nm:enmName) =
        match nm with
            |enmName.Pawn -> "P"
            |enmName.Bishop -> "B"
            |enmName.Knight -> "N"
            |enmName.Rook -> "R"
            |enmName.King -> "K"
            |enmName.Queen -> "Q"
            |_ -> ""
    
    static member create(name,squareord,pciswhite,lastmoveturnno,noofmoves,hasbeenpromoted,id)=
        {
            Name = name;
            SquareOrd = squareord;
            pcIsWhite = pciswhite;
            LastMoveTurnNo = lastmoveturnno;
            NoOfMoves = noofmoves;
            HasBeenPromoted = hasbeenpromoted;
            ID = id;
         }
    static member blank = Piece.create(enmName.Null,-1,false,-1,-1,false,enmID.Null)
    static member copy(p) =
        let cName = p.Name
        let cSquareOrd = p.SquareOrd
        let cpcIsWhite = p.pcIsWhite
        let cLastMoveTurnNo = p.LastMoveTurnNo
        let cNoOfMoves = p.NoOfMoves
        let cHasBeenPromoted = p.HasBeenPromoted
        let cID = p.ID
        Piece.create(cName,cSquareOrd,cpcIsWhite,cLastMoveTurnNo,cNoOfMoves,cHasBeenPromoted,cID)
//move details
type Move =
    {
        mvPiece: int;
        From: int;
        To: int;
        pieceCaptured: int;
        mvName: oMoveName;
        mutable pcLastMoveTurnNo: int;
        Score: int;
        mutable HashCodeA: uint64;
        mutable HashCodeB: uint64;
        OldHashCodeA: uint64;
        OldHashCodeB: uint64;
        mutable TimeStamp: TimeSpan;
        mutable IsThreeMoveRepetition: bool;
        FiftyMoveDrawCounter: int;
        OldScr: int;
    }
    static member create(mvpiece,from,mto,piececaptured,mvname,pclastmoveturnno,score,hashcodea,hashcodeb,oldhashcodea,oldhashcodeb,timestamp,isthreemoverepetition,fiftymovedrawcounter,oldscr) =
        {
            mvPiece = mvpiece;
            From = from;
            To = mto;
            pieceCaptured = piececaptured;
            mvName = mvname;
            pcLastMoveTurnNo = pclastmoveturnno;
            Score = score;
            HashCodeA = hashcodea;
            HashCodeB = hashcodeb;
            OldHashCodeA = oldhashcodea;
            OldHashCodeB = oldhashcodeb;
            TimeStamp = timestamp;
            IsThreeMoveRepetition = isthreemoverepetition;
            FiftyMoveDrawCounter = fiftymovedrawcounter;
            OldScr = oldscr;
        }
    static member blank = Move.create(-1,-1,-1,-1,CastleKingSide,-1,-1,0UL,0UL,0UL,0UL,new TimeSpan(0L),false,-1,-1)
    member m.isBlank() = m.From = -1
    static member copy(m) =
        let cmvPiece = m.mvPiece
        let cFrom = m.From
        let cTo = m.To
        let cpieceCaptured = m.pieceCaptured
        let cmvName = m.mvName
        let cpcLastMoveTurnNo = m.pcLastMoveTurnNo
        let cScore = m.Score
        let cHashCodeA = m.HashCodeA
        let cHashCodeB = m.HashCodeB
        let cOldHashCodeA = m.OldHashCodeA
        let cOldHashCodeB = m.OldHashCodeB
        let cTimeStamp = m.TimeStamp
        let cIsThreeMoveRepetition = m.IsThreeMoveRepetition
        let cFiftyMoveDrawCounter = m.FiftyMoveDrawCounter
        let cOldScr = m.OldScr
        Move.create(cmvPiece,cFrom,cTo,cpieceCaptured,cmvName,cpcLastMoveTurnNo,cScore,cHashCodeA,cHashCodeB,cOldHashCodeA,cOldHashCodeB,cTimeStamp,cIsThreeMoveRepetition,cFiftyMoveDrawCounter,cOldScr)
    member m.isTactical() = 
        match m.mvName with
            |Standard -> if m.pieceCaptured <> -1 then true else false
            |PawnPromotionQueen|PawnPromotionRook|PawnPromotionKnight|PawnPromotionBishop|EnPassent -> true
            |_ -> false
                 
//player clock stores 
type PlayerClock =
    {
        mutable TimeElapsed: TimeSpan;
        mutable TurnStartTime: DateTime;
        mutable IsTicking: bool;
        clIsWhite: bool;
    }
    static member create(timeelapsed,turnstarttime,isticking,cliswhite) =
        {
            TimeElapsed = timeelapsed;
            TurnStartTime = turnstarttime;
            IsTicking = isticking;
            clIsWhite = cliswhite;
        }
    static member blankB = PlayerClock.create(new TimeSpan(0, 0, 0),DateTime.Now,false,false)
    static member blankW = PlayerClock.create(new TimeSpan(0, 0, 0),DateTime.Now,false,true)
    member plc.TimeElapsedDisplay = if plc.IsTicking then plc.TimeElapsed + (DateTime.Now - plc.TurnStartTime) else plc.TimeElapsed
    member plc.Start() = 
        if not plc.IsTicking then
            plc.IsTicking <- true
            plc.TurnStartTime <- DateTime.Now
    member plc.Stop() = 
        if (plc.IsTicking) then
            plc.IsTicking <- false
            plc.TimeElapsed <- plc.TimeElapsed + (DateTime.Now - plc.TurnStartTime)
    member plc.Revert() = 
        plc.IsTicking <- false
        plc.TurnStartTime <- DateTime.Now
    member plc.ControlPeriod(clockMoves,moveNo) =
        if clockMoves = 0 then 1 else (moveNo / clockMoves) + 1
    member plc.TimeRemaining(clockTime:TimeSpan,clockMoves,moveNo,clockIncrementPerMove:TimeSpan) =
        let tsnRepeatingTimeLimit = new TimeSpan(clockTime.Ticks * int64(plc.ControlPeriod(clockMoves,moveNo)) + clockIncrementPerMove.Ticks * int64(moveNo))
        tsnRepeatingTimeLimit - plc.TimeElapsed
    member plc.MovesRemaining(clockMoves,moveNo) =
        let intRepeatingMoves = clockMoves * plc.ControlPeriod(clockMoves,moveNo)
        Math.Max(intRepeatingMoves - moveNo, 0)
//player - too many mutables
type Player =
    {
        mutable ThreadThought: Thread;
        prIsWhite: bool;
        mutable ThinkingTimeMaxAllowed: TimeSpan;
        mutable ThinkingTimeAllotted: TimeSpan;
        mutable ThinkingTimeCutoff: TimeSpan;
        mutable Intellegence: oIntellegence;
        mutable Clock: PlayerClock;
    }
    static member white() =
        {
            ThreadThought = null;
            prIsWhite = true;
            ThinkingTimeMaxAllowed = new TimeSpan(0L);
            ThinkingTimeAllotted = new TimeSpan(0L);
            ThinkingTimeCutoff = new TimeSpan(0L);
            Intellegence = Human;
            Clock=PlayerClock.blankW;
        }
    static member black() =
        {
            ThreadThought = null;
            prIsWhite = false;
            ThinkingTimeMaxAllowed = new TimeSpan(0L);
            ThinkingTimeAllotted = new TimeSpan(0L);
            ThinkingTimeCutoff = new TimeSpan(0L);
            Intellegence = Computer;
            Clock=PlayerClock.blankB;
        }
    
    member pr.SetTime(clockFixedTimePerMove:TimeSpan,clockIncrementPerMove:TimeSpan,moveNo,clockTime:TimeSpan,clockMoves) =
            let timeRemaining = pr.Clock.TimeRemaining(clockTime,clockMoves,moveNo,clockIncrementPerMove).Ticks
            let movesRemaining = pr.Clock.MovesRemaining(clockMoves,moveNo)
            // Time allowed for pr player to think
            if (clockFixedTimePerMove.TotalSeconds > 0.0) then
                // Absolute fixed time per move. No time is carried over from one move to the next.
                pr.ThinkingTimeAllotted <- clockFixedTimePerMove
            elif (clockIncrementPerMove.TotalSeconds > 0.0) then
                // Incremental clock
                pr.ThinkingTimeAllotted <- new TimeSpan(clockIncrementPerMove.Ticks + ((clockIncrementPerMove.Ticks * int64(moveNo) + clockTime.Ticks * int64(Math.Min(moveNo, 40) / 40)) - pr.Clock.TimeElapsed.Ticks) / 3L)
                // Make sure we never think for less than half the "Increment" time
                pr.ThinkingTimeAllotted <- new TimeSpan(Math.Max(pr.ThinkingTimeAllotted.Ticks, clockIncrementPerMove.Ticks / 2L + 1L))
            elif (clockMoves = 0 && clockIncrementPerMove.TotalSeconds = 0.0) then
                // Fixed game time
                pr.ThinkingTimeAllotted <- new TimeSpan(timeRemaining / 30L)
            else
                // Conventional n moves in x minutes time
                pr.ThinkingTimeAllotted <- new TimeSpan(timeRemaining / int64(movesRemaining))
            // Minimum of 1 second thinking time
            if (pr.ThinkingTimeAllotted.TotalSeconds < 1.0) then
                pr.ThinkingTimeAllotted <- new TimeSpan(0, 0, 1)
            // The computer only stops "thinking" when it has finished a full ply of thought, 
            // UNLESS ThinkingTimeMaxAllowed is exceeded, or clock runs out, then it stops right away.
            if (clockFixedTimePerMove.TotalSeconds > 0.0) then
                // Fixed time per move
                pr.ThinkingTimeMaxAllowed <- clockFixedTimePerMove
            else
                // Variable time per move
                pr.ThinkingTimeMaxAllowed <- new TimeSpan(Math.Min(pr.ThinkingTimeAllotted.Ticks * 2L, timeRemaining - (new TimeSpan(0, 0, 0, 2)).Ticks))
            // Minimum of 1 second thinking time
            if (pr.ThinkingTimeMaxAllowed.TotalSeconds < 2.0) then
                pr.ThinkingTimeMaxAllowed <- new TimeSpan(0, 0, 2)
            // A new deeper ply of search will only be started, IF the cutoff time hasnt been reached yet.
            pr.ThinkingTimeCutoff <- new TimeSpan(pr.ThinkingTimeAllotted.Ticks / 3L)

//posn - used for current position but also as anlysis progresses
type Posn =
    {
        Sqs:int[];
        Pcs:Piece[];
        mutable Hca:uint64;
        mutable Hcb:uint64;
        mutable Trn:int;
        mutable Bcas:bool;
        mutable Wcas:bool;
        mutable Bct:int;
        mutable Wct:int;
        Mhst:ResizeArray<Move>;
        MhstStr:ResizeArray<string>;
        mutable PlayerToPlay:Player;
        mutable Scr:int;
    }
    static member create(sqs,pcs,hca,hcb,trn,bcas,wcas,bct,wct,mhst,mhststr,playertoplay,scr) =
        {
            Sqs = sqs;
            Pcs = pcs;
            Hca = hca;
            Hcb = hcb;
            Trn = trn;
            Bcas = bcas;
            Wcas = wcas;
            Bct = bct;
            Wct = wct;
            Mhst = mhst;
            MhstStr = mhststr;
            PlayerToPlay = playertoplay;
            Scr = scr;
        }
    static member blank = Posn.create(Array.create Ref.SQUARE_COUNT -1,Array.zeroCreate 32 ,0UL,0UL,0,false,false,16,16,new ResizeArray<Move>(),new ResizeArray<string>(),Player.white(),-1)
    member p.SetPiecesAtStartingPositions() =
        let CreatePiece(name,col,c,r,ID) =
            let ord = Ref.GetOrdFR (c,r)
            let pc = Piece.create(name,ord,col,-1,0,false,ID)
            p.Sqs.[ord] <- (int)ID
            p.Pcs.[(int)ID] <- pc
        List.iter CreatePiece [(enmName.King, false, 4,7, enmID.BlackKing);
            (enmName.Queen, false, 3,7, enmID.BlackQueen); 
            (enmName.Rook, false, 0,7, enmID.BlackQueensRook);
            (enmName.Rook, false, 7,7, enmID.BlackKingsRook);  
            (enmName.Bishop, false, 2,7, enmID.BlackQueensBishop);
            (enmName.Bishop, false, 5,7, enmID.BlackKingsBishop); 
            (enmName.Knight, false, 1,7, enmID.BlackQueensKnight);
            (enmName.Knight, false, 6,7, enmID.BlackKingsKnight);
            (enmName.Pawn, false, 0,6, enmID.BlackPawn1);
            (enmName.Pawn, false, 1,6, enmID.BlackPawn2);
            (enmName.Pawn, false, 2,6, enmID.BlackPawn3);
            (enmName.Pawn, false, 3,6, enmID.BlackPawn4);
            (enmName.Pawn, false, 4,6, enmID.BlackPawn5);
            (enmName.Pawn, false, 5,6, enmID.BlackPawn6);
            (enmName.Pawn, false, 6,6, enmID.BlackPawn7);
            (enmName.Pawn, false, 7,6, enmID.BlackPawn8);
            (enmName.King, true, 4,0, enmID.WhiteKing);
            (enmName.Queen, true, 3,0, enmID.WhiteQueen);
            (enmName.Rook, true, 0,0, enmID.WhiteQueensRook);
            (enmName.Rook, true, 7,0, enmID.WhiteKingsRook); 
            (enmName.Bishop, true, 2,0, enmID.WhiteQueensBishop);
            (enmName.Bishop, true, 5,0, enmID.WhiteKingsBishop);
            (enmName.Knight, true, 1,0, enmID.WhiteQueensKnight);
            (enmName.Knight, true, 6,0, enmID.WhiteKingsKnight);
            (enmName.Pawn, true, 0,1, enmID.WhitePawn1);
            (enmName.Pawn, true, 1,1, enmID.WhitePawn2);
            (enmName.Pawn, true, 2,1, enmID.WhitePawn3);
            (enmName.Pawn, true, 3,1, enmID.WhitePawn4);
            (enmName.Pawn, true, 4,1, enmID.WhitePawn5); 
            (enmName.Pawn, true, 5,1, enmID.WhitePawn6);
            (enmName.Pawn, true, 6,1, enmID.WhitePawn7);
            (enmName.Pawn, true, 7,1, enmID.WhitePawn8);]
    static member start =
        let ps = Posn.blank 
        ps.SetPiecesAtStartingPositions()           
        ps
    member p.canK = p.Pcs.[4].NoOfMoves=0 && p.Pcs.[7].NoOfMoves=0 && p.Pcs.[7].SquareOrd<> -1
    member p.canQ = p.Pcs.[4].NoOfMoves=0 && p.Pcs.[0].NoOfMoves=0 && p.Pcs.[0].SquareOrd<> -1
    member p.cank = p.Pcs.[20].NoOfMoves=0 && p.Pcs.[23].NoOfMoves=0 && p.Pcs.[23].SquareOrd<> -1
    member p.canq = p.Pcs.[20].NoOfMoves=0 && p.Pcs.[16].NoOfMoves=0 && p.Pcs.[16].SquareOrd<> -1
    member p.copy()=
        let cSqs = Array.copy p.Sqs
        let cPcs = Array.map Piece.copy p.Pcs
        let cHca = p.Hca
        let cHcb = p.Hcb
        let cTrn = p.Trn
        let cBcas = p.Bcas
        let cWcas = p.Wcas
        let cWct = p.Wct
        let cBct = p.Bct
        let cMhst = ResizeArray.map Move.copy p.Mhst
        let cMhstStr = ResizeArray.map String.Copy p.MhstStr
        let cPlayerToPlay = p.PlayerToPlay
        let cScr = p.Scr
        Posn.create(cSqs,cPcs,cHca,cHcb,cTrn,cBcas,cWcas,cWct,cBct,cMhst,cMhstStr,cPlayerToPlay,cScr)
    member p.SetMaterialCount() =
        p.Wct <- 0
        for i = 0 to 15 do
            if p.Pcs.[i].SquareOrd<> -1 then p.Wct <- p.Wct+1
        p.Bct <- 0
        for i = 16 to 31 do
            if p.Pcs.[i].SquareOrd<> -1 then p.Bct <- p.Bct+1
    member p.CreateMove(mvname,mvpiece,from,mto,piececaptured,score) =
        let mFiftyMoveDrawCounter = if (mvname <> NullMove && piececaptured = -1 && p.Pcs.[mvpiece].Name <> enmName.Pawn) then (if p.Mhst.Count > 0 then p.Mhst.[p.Mhst.Count - 1].FiftyMoveDrawCounter + 1 else -Ref.FiftyMoveDrawBase / 2 + 1) else 0
        Move.create(mvpiece,from,mto,piececaptured,mvname,p.Trn,score,0UL,0UL,p.Hca,p.Hcb,new TimeSpan(0L),false,mFiftyMoveDrawCounter,p.Scr)        
    member p.ToFen() =
        // Field 1: Piece placement data
        let fen1 =
            let mutable ans = ""
            let mutable iNbrEmptySquare = 0
            for indRank = 7 downto 0 do
                if indRank <> 7 then
                    ans <- ans+"/"
                for indFile = 0 to 7 do
                    let ordThis = Ref.GetOrdFR(indFile, indRank)
                    let pieceThis = p.Sqs.[ordThis]
                    if (pieceThis = -1) then
                        iNbrEmptySquare<-iNbrEmptySquare+1
                    else
                        if (iNbrEmptySquare > 0) then
                            ans<-ans+iNbrEmptySquare.ToString()
                            iNbrEmptySquare <- 0
                        if (pieceThis>15) then
                            ans<-ans+Piece.abbrev(p.Pcs.[pieceThis].Name).ToLower()
                        else
                            ans<-ans+Piece.abbrev(p.Pcs.[pieceThis].Name)
                if (iNbrEmptySquare > 0) then
                    ans<-ans+iNbrEmptySquare.ToString()
                    iNbrEmptySquare <- 0
            ans
        // Field 2: Active colour
        let fen2 = if (p.Trn%2=0) then " w " else " b "
        // Field 3: Castling availability
        let fen3 =
            let mutable ans = ""
            if p.canK then ans <- "K"
            if p.canQ then ans <- ans+"Q"
            if p.cank then ans <- ans+"k"
            if p.canq then ans <- ans+"q"
            if ans="" then ans <- "-"
            ans    
        // Field 4: En passant target square coordonates
        let fen4 =
            if (p.Mhst.Count > 0) then
                let lastMove = p.Mhst.[p.Mhst.Count - 1]
                let lastMovepcid = lastMove.mvPiece
                let lastMovepc = p.Pcs.[lastMovepcid]
                if lastMovepc.Name = enmName.Pawn && Ref.fi.[lastMove.From] = Ref.fi.[lastMove.To] && (((Ref.ri.[lastMove.From] = Ref.ri.[lastMove.To] + 2) && (not lastMovepc.pcIsWhite)) || ((Ref.ri.[lastMove.From] = Ref.ri.[lastMove.To] - 2) && (lastMovepc.pcIsWhite))) then
                    " " + Ref.f.[lastMove.From] + (if (lastMovepc.pcIsWhite) then "3 " else "6 ") // The case between From and To
                else
                    " - "
            else
                " - "// There is not en passant target square
        // Field 5: number of Halfmove clock or ply since the last pawn advance or capturing move.
        let fen5 = String.Format("{0} ", ( if p.Mhst.Count > 0 then p.Mhst.[p.Mhst.Count - 1].FiftyMoveDrawCounter else 0))
        // Field 6: Full move number
        let fen6 = ((p.Trn >>> 1) + 1).ToString() 
        fen1+fen2+fen3+fen4+fen5+fen6
//anal - used for analysis
type Anal =
    {
        Psn: Posn;
        mutable PosSearched: int;
        mutable SearchDepth: int;
    }
    static member create(psn,possearched,searchdepth) =
        {
            Psn=psn;
            PosSearched=possearched;
            SearchDepth=searchdepth;
        }
    member a.set(psn:Posn,maximumSearchDepth) = Anal.create(psn.copy(),0,0)
    member a.copy() =
        let cPsn = a.Psn.copy()
        let cPosSearched = a.PosSearched
        let cSearchDepth = a.SearchDepth
        Anal.create(cPsn,cPosSearched,cSearchDepth)

//anals - used for an array of analysis - multicore
type Anals =
    {
        mutable Anl:Anal;
        mutable PrincVar: ResizeArray<Move>;
        MinSearchDepth: int;
        MaxSearchDepth: int;
        ImmMov: bool ref;
    }
    static member create(anl,princVar,minsearchdepth,maxsearchdepth,immMov) =
        {
            Anl = anl;
            PrincVar = princVar;
            MinSearchDepth = minsearchdepth;
            MaxSearchDepth = maxsearchdepth;
            ImmMov = immMov;
        } 
    member a.set(psn,maximumSearchDepth) = a.Anl <- a.Anl.set(psn,maximumSearchDepth)
    member a.setSearchDepth(i) = a.Anl.SearchDepth<-i
    //need to put a lock on these
    member a.setimm(b) = lock a.ImmMov (fun () ->  if a.PrincVar.Count>0 then a.ImmMov := b)
    member a.getimm() = lock a.ImmMov (fun () ->  !a.ImmMov)
    
type OpHash = System.Collections.Generic.Dictionary<string,string list>
//tracks move generation
exception InvalidMpGenType
type MpGenType =
    |GenAll
    |GenEvasions
    |GenCaptures
exception InvalidMpState
type MpState =
    |DoneAll
    |DoneHash
    |DoneEvasions
    |DoneCaptures
    |DoneNothing
    |DoneGoodCaptures
    |DoneBadCaptures
    |DoneKillA
    |DoneKillB    
type MvsPoss =
    {
        GnType:MpGenType;
        mutable State:MpState;
        Mvs:ResizeArray<Move>;
        Capl:ResizeArray<Move>;
        Bcapl:ResizeArray<Move>;
        mutable KillA:Move;
        mutable KillB:Move;
        Othl:ResizeArray<Move>;
        Evasl:ResizeArray<Move>;
    }
    static member create(gntype,state,mvs,capl,bcapl,killa,killb,othl,evasl) =
        {
            GnType =gntype;
            State = state;
            Mvs = mvs;
            Capl = capl;
            Bcapl = bcapl;
            KillA = killa;
            KillB = killb;
            Othl = othl;
            Evasl = evasl;
        }   
    static member start() =
        let mvs = new ResizeArray<Move>()
        mvs.Capacity <- 150
        let capl = new ResizeArray<Move>()
        capl.Capacity <- 80
        let bcapl = new ResizeArray<Move>()
        bcapl.Capacity <- 80
        let killa = Move.blank
        let killb = Move.blank
        let othl = new ResizeArray<Move>()
        othl.Capacity <- 150
        let evasl = new ResizeArray<Move>()
        evasl.Capacity <- 80
        MvsPoss.create(GenAll,DoneNothing,mvs,capl,bcapl,killa,killb,othl,evasl)
    static member newtyp(gntype) =
        let mvs = new ResizeArray<Move>()
        mvs.Capacity <- 150
        let capl = new ResizeArray<Move>()
        capl.Capacity <- 80
        let bcapl = new ResizeArray<Move>()
        bcapl.Capacity <- 80
        let killa = Move.blank
        let killb = Move.blank
        let othl = new ResizeArray<Move>()
        othl.Capacity <- 150
        let evasl = new ResizeArray<Move>()
        evasl.Capacity <- 80
        MvsPoss.create(gntype,DoneNothing,mvs,capl,bcapl,killa,killb,othl,evasl)

        